// 
// Bachelor of Software Engineering
// Media Design School
// Auckland
// New Zealand
//
// (c) 2005 - 2014 Media Design School
//
// File Name	: CCardStack.h
// Desrciption	: CCardStack declaration file.
// Author(s)	: Hayden Asplet.
// Mail			: hayden.asplet@mediadesignschool.com
//

#pragma once

#ifndef __CARDSTACK_H__
#define __CARDSTACK_H__

// Library Includes

// Local Includes
#include "PlayingCard.h"

enum EStackDirection {
	keDown,
	keRight,
	keBoth
};

// ===========================================================
// CCardStack is a class that stores playing cards in a stack
// data structure.
// 
// It defines Push, Pop and Peek methods, as well as the 
// ability to push and pop entire sub-stacks. This is helpful
// when moving around entire stacks instead of just individual
// cards.
// ===========================================================

typedef std::vector<CPlayingCard> TStack;
typedef std::list<CPlayingCard> TCardList;

class CCardStack {
	// Member Functions
public:
	// Constructor
	CCardStack();
	CCardStack(const CPoint& _krPosition, int _iOffset = 0, const EStackDirection& _kreDirection = keDown);
	CCardStack(const CCardStack& _krStack);

	// Destructor
	virtual ~CCardStack();

	bool IsOverlapping(const CPoint& _krPosition);	// True if position overlaps the last card on stack, false otherwise.
	bool IsOverlapping(const CRect& _krRect);		// True if Rect overlaps the last Rect on the stack, false otherwise.
	int GetOverlapping(const CPoint& _krPosition);	// Returns the index of the card that the position overlaps.

	// =======================================================
	// These functions make up the functionality of the stack.
	// They should be overidden in derived classes to redefine
	// how the stack works within the game.
	// =======================================================
	virtual bool CanBePushed(const CPlayingCard& _krCard);
	virtual bool CanBePushed(const CCardStack& _krStack);

	virtual CPoint VGetNextPosition() const;		// Retrieves the position of the next card, if it were to be placed.
	
	virtual void VUpdatePositions();

	// =======================================================
	// These push methods do not check if the desired card or
	// stack can be pushed.
	// =======================================================
	void Push(const CPlayingCard& _krCard);
	void Push(const TStack& _krStack);

	void Pop();							// Removes the top card.
	TStack PopStack(int _iIndex = 0);	// Removes and returns all cards at the index and above.
	CCardStack PopSubStack(int _iIndex = 0); // Removes all cards at the index but returns a card stack. 

	void PushLerping(const CPlayingCard& _krCard);
	void PushLerping(const TStack& _krStack);
	void PopLerping();

	void Shuffle();
	void Clear();

	bool IsEmpty() const;
	int Size() const;

	// Accessors
	const TStack& GetStack() const;
	CPlayingCard& operator[](int _iIndex);
	const CPlayingCard& operator[](int _iIndex) const;

	CPlayingCard& Peek();
	const CPlayingCard& Peek() const;

	void SetOffset(int _iOffset);
	void SetPosition(const CPoint& _krPosition);
	void SetDirection(EStackDirection _eDirection);

	int GetOffset() const;
	const CPoint& GetPosition() const;				// Retrieves the position of the bottom card.
	CRect GetTopRect() const;						// Retrieves the rectangle of the top card.
	const EStackDirection& GetDirection() const;
protected:
private:

	// Member Variables
public:
protected:
	TStack m_cards;				// The cards.
	TCardList m_lerpingCards;	// The cards that are being lerped here.

	CPoint m_position;					// The position of the bottom card.
	int m_iOffset;						// The amount of pixels to offset each card.
	EStackDirection m_eDirection;		// The direction at which to offset each card.
private:
};

#endif